﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Axe.Geometry
{
    public class Matrix2
    {
        public double[] _elements = new double[9];


        public Matrix2()
        {
            SetToIdentity();
        }

        #region public double this[int row, int col]
        /// <summary>
        /// Доступ к элементам матрицы
        /// </summary>
        /// <param name="row">Номер строки</param>
        /// <param name="col">Номер столбца</param>
        /// <returns>Значение указанного элемента</returns>
        public double this[int row, int col]
        {
            get
            {
                return _elements[row + col * 3];
            }
            set
            {
                _elements[row + col * 3] = value;
            }
        }
        #endregion

        #region public void SetToIdentity()
        /// <summary>
        /// Сброс матрицы в единичную
        /// </summary>
        public void SetToIdentity()
        {
            this[0, 0] = 1; this[0, 1] = 0; this[0, 2] = 0;
            this[1, 0] = 0; this[1, 1] = 1; this[1, 2] = 0;
            this[2, 0] = 0; this[2, 1] = 0; this[2, 2] = 1;
        } 
        #endregion

        #region static public Matrix2 FromMultiplication(Matrix2 m0, Matrix2 m1)
        /// <summary>
        /// Перемножение матриц
        /// </summary>
        /// <param name="m0"></param>
        /// <param name="m1"></param>
        /// <returns></returns>
        static public Matrix2 FromMultiplication(Matrix2 m0, Matrix2 m1)
        {
            Matrix2 res = new Matrix2();

            for (int j = 0; j < 3; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    res[j, k] = m0[j, 0] * m1[0, k] + m0[j, 1] * m1[1, k] + m0[j, 2] * m1[2, k];
                }
            }

            return res;
        } 
        #endregion

        public static Matrix2 FromRotation(double degree)
        {
            Matrix2 m = new Matrix2();

            m[0, 0] = Math.Cos(degree); m[0, 1] = Math.Sin(degree);
            m[1, 0] = -Math.Sin(degree); m[1, 1] = Math.Cos(degree);

            return m;
        }

        public static Matrix2 operator *(Matrix2 m1, Matrix2 m2)
        {
            return FromMultiplication(m1, m2);
        }

        #region public static Vector2Collection operator *(Matrix2 m, Vector2Collection c)
        /// <summary>
        /// Умножение матрицы на все элементы коллекции
        /// </summary>
        /// <param name="m"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static Vector2Collection operator *(Matrix2 m, Vector2Collection c)
        {
            Vector2Collection v2c = new Vector2Collection();

            v2c.ForEach(delegate(Vector2 v) { v2c.Add(m * v); });

            return v2c;
        } 
        #endregion

        #region public static Vector2 operator *(Matrix2 m, Vector2 v)
        public static Vector2 operator *(Matrix2 m, Vector2 v)
        {
            Vector2 r = new Vector2();
            double x = v.X, y = v.Y;
            r.X = x * m[0, 0] + y * m[0, 1] + m[0, 2];
            r.Y = x * m[1, 0] + y * m[1, 1] + m[1, 2];
            return r;

        } 
        #endregion

        public static Matrix2 FromTranslation(double x, double y)
        {
            Matrix2 m = new Matrix2();

            m[0, 2] = x;
            m[1, 2] = y;

            return m;
        }
    }
}
